﻿#If NETFX_CORE Then
Imports Windows.Foundation
Imports Windows.Foundation.Metadata
Imports Windows.UI
Imports Windows.Storage.Streams
Imports System.Runtime.InteropServices.WindowsRuntime
#End If

Imports Microsoft.Xna.Framework.Graphics
Imports System.Reflection
Imports System.Runtime.CompilerServices

Namespace Global.Microsoft.Xna.Framework

    Public Module Extension

        <Extension> _
        Public Function ToPoint(ByVal source As Vector2) As Point
            Return New Point(CInt(source.X + 0.5), CInt(source.Y + 0.5))
        End Function

        <Extension> _
        Public Function ToVector2(ByVal source As Point) As Vector2
            Return New Vector2(CSng(source.X), CSng(source.Y))
        End Function

        <Extension()> _
        Public Function GetPureColorTexture(ByVal c As Microsoft.Xna.Framework.Color, ByVal width As Integer, ByVal height As Integer, ByVal g As GraphicsDevice) As Texture2D
            Dim bitmap As New Texture2D(g, width, height)
            Dim buffer(0) As Microsoft.Xna.Framework.Color
            Array.Resize(buffer, bitmap.Width * bitmap.Height)
            bitmap.GetData(Of Microsoft.Xna.Framework.Color)(buffer)
            For i As Integer = 0 To buffer.Length - 1
                buffer(i) = c
            Next
            bitmap.SetData(Of Microsoft.Xna.Framework.Color)(buffer)
            Return bitmap
        End Function

        <Extension()> _
        Public Function GenerateRetangleTexture(ByVal rect As Rectangle, ByVal g As GraphicsDevice, Optional ByVal width As Integer = 1, Optional ByVal c As Color? = Nothing) As Texture2D
            If c.HasValue = False Then c = Color.Black
            Dim bitmap As New Texture2D(g, rect.Width, rect.Height)
            Dim buffer(0) As Microsoft.Xna.Framework.Color
            Array.Resize(buffer, bitmap.Width * bitmap.Height)
            bitmap.GetData(Of Microsoft.Xna.Framework.Color)(buffer)
            For i As Integer = 0 To rect.Width - 1
                For j As Integer = 0 To rect.Height - 1
                    If i = 0 Or j = 0 Then
                        buffer(i * rect.Height + j) = c
                    Else
                         buffer(i * rect.Height + j) = color.Transparent
                    End If
                Next
            Next
            bitmap.SetData(Of Microsoft.Xna.Framework.Color)(buffer)
            Return bitmap
        End Function

        ''' <summary>
        ''' Calculates the signed depth of intersection between two rectangles.
        ''' </summary>
        ''' <returns>
        ''' The amount of overlap between two intersecting rectangles. These
        ''' depth values can be negative depending on which wides the rectangles
        ''' intersect. This allows callers to determine the correct direction
        ''' to push objects in order to resolve collisions.
        ''' If the rectangles are not intersecting, Vector2.Zero is returned.
        ''' </returns>
        <Extension> _
        Public Function GetIntersectionDepth(ByVal rectA As Rectangle, ByVal rectB As Rectangle) As Vector2
            ' Calculate half sizes.
            Dim halfWidthA As Single = rectA.Width / 2.0F
            Dim halfHeightA As Single = rectA.Height / 2.0F
            Dim halfWidthB As Single = rectB.Width / 2.0F
            Dim halfHeightB As Single = rectB.Height / 2.0F

            ' Calculate centers.
            Dim centerA As New Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA)
            Dim centerB As New Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB)

            ' Calculate current and minimum-non-intersecting distances between centers.
            Dim distanceX As Single = centerA.X - centerB.X
            Dim distanceY As Single = centerA.Y - centerB.Y
            Dim minDistanceX As Single = halfWidthA + halfWidthB
            Dim minDistanceY As Single = halfHeightA + halfHeightB

            ' If we are not intersecting at all, return (0, 0).
            If Math.Abs(distanceX) >= minDistanceX OrElse Math.Abs(distanceY) >= minDistanceY Then
                Return Vector2.Zero
            End If

            ' Calculate and return intersection depths.
            Dim depthX As Single = If(distanceX > 0, minDistanceX - distanceX, -minDistanceX - distanceX)
            Dim depthY As Single = If(distanceY > 0, minDistanceY - distanceY, -minDistanceY - distanceY)
            Return New Vector2(depthX, depthY)
        End Function

#If NETFX_CORE Then

        <Extension()> _
        Public Function ToXnaColor(ByVal c As Global.Windows.UI.Color) As Microsoft.Xna.Framework.Color
            Return Microsoft.Xna.Framework.Color.FromNonPremultiplied(c.R, c.G, c.B, c.A)
        End Function

        <Extension()> _
        Public Function GetPureColorTexture(ByVal c As Global.Windows.UI.Color, ByVal width As Integer, ByVal height As Integer) As WriteableBitmap
            Dim bitmap As New WriteableBitmap(width, height)
            Dim buffer(4 * width * height - 1) As Byte
            For x As Integer = 0 To width - 1
                For y As Integer = 0 To height - 1
                    Dim index = 4 * (y * width + x)
                    buffer(index + 0) = c.B
                    buffer(index + 1) = c.G
                    buffer(index + 2) = c.R
                    buffer(index + 3) = c.A
                Next
            Next
            Dim pixelStream = bitmap.PixelBuffer.AsStream()
            pixelStream.Seek(0, SeekOrigin.Begin)
            pixelStream.Write(buffer, 0, buffer.Length)
            bitmap.Invalidate()
            Return bitmap
        End Function

#Else

#End If

#If Not SILVERLIGHT Then

        ''' <summary>
        ''' Try to change the current resolution.
        ''' If failed, it keeps the original value.
        ''' </summary>
        ''' <param name="Me"></param>
        ''' <param name="size"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        <Extension()> _
        <Extension()> Public Function TryChangeResolution(ByVal [Me] As GraphicsDeviceManager, ByVal size As Vector2, Optional ByRef ori As Vector2 = Nothing) As Boolean
            ori = New Vector2([Me].PreferredBackBufferWidth, [Me].PreferredBackBufferHeight)
            Try
                With [Me]
                    .PreferredBackBufferHeight = CInt(size.Y)
                    .PreferredBackBufferWidth = CInt(size.X)
                End With
                [Me].ApplyChanges()
                Return True
            Catch ex As Exception
                Return False
            End Try
        End Function

#End If

    End Module

End Namespace